"""
@File    :   route_depend.py
@Time    :   2024/03/28 23:35:28
@Author  :   Qrj
@Email   :   923207736@qq.com
@description   :   路由依赖(用于维持本业务的路由部分整洁)
"""

from typing import Annotated, Literal

from fastapi import Body, Depends
from pydantic import conint
from redis.asyncio import Redis

from src.business.admin.system.oauth2.auth.captcha.utils.image import ImageCaptchaUtil
from src.business.admin.system.oauth2.auth.captcha.utils.sliding_puzzle import (
    SlidingPuzzleCaptchaUtil,
)
from src.config import Settings
from src.dependencies.no_introduction import (
    depend_get_app_settings,
    depend_get_cache_redis_pool,
)
from src.exceptions.custom_async_validator import generate_async_validator_exception


class RouteDependRandomGetImageCaptcha:
    """随机获取图像验证码ID与图像信息的路由依赖类"""

    def __init__(self):
        self.code_id: str | None = None
        self.images_base64_str: str | None = None

    async def __call__(
        self,
        cache_redis_pool: Annotated[Redis, Depends(depend_get_cache_redis_pool)],
    ) -> "RouteDependRandomGetImageCaptcha":
        (
            self.code_id,
            self.images_base64_str,
        ) = await ImageCaptchaUtil.random_get_image_captcha(cache_redis_pool)
        return self


# 实例化随机获取图像验证码ID与图像信息的路由依赖类
route_depend_random_get_image_captcha = RouteDependRandomGetImageCaptcha()


async def route_depend_verify_image_captcha(
    code_id: Annotated[str, Body(default=..., min_length=1, max_length=256)],
    code_answer: Annotated[str, Body(default=..., min_length=1, max_length=10)],
    cache_redis_pool: Annotated[Redis, Depends(depend_get_cache_redis_pool)],
) -> bool:
    """验证图像验证码的路由依赖"""
    result = await ImageCaptchaUtil.validate_image_captcha(
        cache_redis_pool, code_id, code_answer
    )
    if result is None:
        # 没找到则报图像验证码过期异常
        raise generate_async_validator_exception("code_id", "图像验证码已过期")

    if not result:
        # 答案错误则报图像验证码答案错误异常
        raise generate_async_validator_exception("code_answer", "图像验证码答案错误")
    return True


class RouteDependRandomGetSlidingCaptcha:
    """随机获取滑动验证码ID与相关图像信息的路由依赖类"""

    def __init__(self):
        self.code_id: str | None = None
        self.base_img_base64_str: str | None = None
        self.slide_base64_str: str | None = None

    async def __call__(
        self,
        cache_redis_pool: Annotated[Redis, Depends(depend_get_cache_redis_pool)],
    ) -> "RouteDependRandomGetSlidingCaptcha":
        (
            self.code_id,
            self.base_img_base64_str,
            self.slide_base64_str,
        ) = await SlidingPuzzleCaptchaUtil.random_get_sliding_captcha(cache_redis_pool)
        return self


# 实例化随机获取滑动验证码ID与相关图像信息的路由依赖类
route_depend_random_get_sliding_captcha = RouteDependRandomGetSlidingCaptcha()


async def route_depend_verify_sliding_captcha(
    code_id: Annotated[
        str, Body(default=..., min_length=1, max_length=256, description="验证码ID")
    ],
    code_answer: Annotated[
        dict[Literal["x", "y"], conint(ge=0)],
        Body(default=..., description="验证码答案"),
    ],
    cache_redis_pool: Annotated[Redis, Depends(depend_get_cache_redis_pool)],
    app_settings: Annotated[Settings, Depends(depend_get_app_settings)],
) -> bool:
    """验证滑动验证码的路由依赖"""
    result = await SlidingPuzzleCaptchaUtil.validate_sliding_captcha(
        cache_redis_pool,
        code_id,
        code_answer,
        max_error_value=app_settings.sliding_captcha_max_error_value,
    )
    if result is None:
        # 没找到则报滑动验证码过期异常
        raise generate_async_validator_exception("code_answer", "滑动验证码已过期")

    if not result:
        # 答案错误则报滑块验证码验证失败异常
        raise generate_async_validator_exception("code_answer", "滑动验证码答案错误")
    return True
